package com.rad.statistics.android;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;

import com.rad.net.protocol.android.NetTask;
import com.rad.statistics.common.BaseEvent;
import com.rad.statistics.common.cmd.StatisticsCmd;
import com.rad.statistics.common.result.Statistics;

/**
 * 类说明：统计引擎类，对触发事件进行统计，上传统计数据。指定上传数据的url， 可控制是否只在wifi情况下才上传数据。<br>
 * 用法：
 * <li>使用前必须使用{@link NetTask#setup(String, String, String, String)}对
 * {@link NetTask}进行初始化
 * <li>需要指定数据上传地址时，使用{@link #setStatisticsUrl(String)};
 * <li>在需要统计的触发事件中，使用{@link #onEvent(Context, BaseEvent)}或者是
 * {@link #onEvent(Context, String)}进行统计
 * <li>设置只在wifi下上传数据，通过 {@link #setPostDataWifiOnly(boolean)}
 * <li>在需要立刻上传本地存储的数据时，使用 {@link #postDataImmediately(Context)}
 * 
 * @author kalui.huang
 * @date 2014-10-17
 * @version 1.0
 */
public class StatisticsAgent {
	private final static String TAG = StatisticsAgent.class.getSimpleName();
	private static Handler sHandler;
	private static boolean sWifiOnly = false;
	// http://dev.aijiaoyan.com:8888/adc/xxx?vc=版本代码&vn=版本名称&sv=统计程序版本号,
	// xxx为APP包名, 如: a.b.c

	// private static String sUrl = "http://192.168.1.201:8888/adc"; // 测试地址
	private static String sUrl = "http://47.98.213.202/adc"; // 正式地址

	/**
	 * 设置统计的链接地址
	 * 
	 * @param statisticsUrl
	 * 
	 */
	public static void setStatisticsUrl(String statisticsUrl) {
		sUrl = statisticsUrl;
	}

	/**
	 * 初始化handler
	 */
	static {
		HandlerThread workHandlerThread = new HandlerThread(TAG);
		workHandlerThread.start();
		sHandler = new Handler(workHandlerThread.getLooper());
	}

	/**
	 * 设置是否只在wifi的情况下上传统计数据
	 * 
	 * @param wifiOnly
	 *            默认为false
	 */
	public static void setPostDataWifiOnly(boolean wifiOnly) {
		sWifiOnly = wifiOnly;
	}

	/**
	 * 对触发事件进行统计
	 * 
	 * @param context
	 * @param event
	 *            继承{@link BaseEvent}的事件对象
	 */
	public static void onEvent(final Context context, final BaseEvent event) {
		if (event == null) {
			throw new IllegalArgumentException("event must not be null");
		}
		Runnable eventInfo = new Runnable() {
			public void run() {
				postEvent(context, event);
			}
		};
		sHandler.post(eventInfo);
	}

	/**
	 * 对触发事件进行统计
	 * 
	 * @param context
	 * @param eventName
	 *            触发事件名称
	 */
	public static void onEvent(Context context, String eventName) {
		if (TextUtils.isEmpty(eventName)) {
			throw new IllegalArgumentException("eventName must not be empty");
		}
		BaseEvent event = new BaseEvent();
		event.setEventName(eventName);
		onEvent(context, event);
	}

	private static void postEvent(Context context, BaseEvent event) {
		StatisticsCmd statisticsCmd = EventFormat.onFormat(context, event);
		StatisticsCmd localLimitedCmd = DataStorage.getLimitedCmd(context);
		if (localLimitedCmd != null) {
			DataStorage.mergeCmd(context, statisticsCmd, localLimitedCmd);
		}
		// DataStorage.mergeCmd(context, statisticsCmd);
		// 是否是wifi网络环境
		boolean isWifiNow = "wifi".equalsIgnoreCase(event.getNetworkEnvironment());
		if (sWifiOnly && !isWifiNow) {
			saveCmdWithoutGzip(context, statisticsCmd);
		} else {
			post(context, statisticsCmd);
		}
	}

	/**
	 * 立刻上传统计数据，无论是在何种网络情况下
	 * 
	 * @param context
	 */
	public static void postDataImmediately(final Context context) {
		Runnable data = new Runnable() {
			public void run() {
				postData(context);
			}
		};
		sHandler.post(data);
	}

	/**
	 * 获取本地存储统计数据进行发送
	 * 
	 * @param context
	 */
	private static void postData(Context context) {
		StatisticsCmd statisticsCmd = DataStorage.getLimitedCmd(context);
		if (statisticsCmd != null) {
			post(context, statisticsCmd);
		}
	}

	/**
	 * 联网发送数据
	 * 
	 * @param context
	 * @param statisticsCmd
	 *            统计数据cmd
	 */
	private static void post(Context context, StatisticsCmd statisticsCmd) {

		if (TextUtils.isEmpty(sUrl)) {
			throw new IllegalArgumentException("statisticsUrl must be set, use setStatisticsUrl() to complete it");
		} else {
			statisticsCmd.setServerUrl(sUrl);

			Object result = StatisticsNet.sendData(context, statisticsCmd);

			if (!(result instanceof Statistics)) {
				saveCmdWithoutGzip(context, statisticsCmd);
			} else {
				StatisticsCmd localLimitedCmd = DataStorage.getLimitedCmd(context);
				if (localLimitedCmd != null) {
					post(context, localLimitedCmd);
				}
			}
		}
	}

	private static void saveCmdWithoutGzip(Context context, StatisticsCmd statisticsCmd) {
		// 不序列化存储gzipData字段数据
		statisticsCmd.setGzipData(null);
		StatisticsCmd localAllCmd = DataStorage.getAllCmd(context);
		if (localAllCmd != null) {
			DataStorage.mergeCmd(context, statisticsCmd, localAllCmd);
		}
		DataStorage.saveCmd(context, statisticsCmd);
	}
}
